package com.wms_backend.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.wms_backend.dao.FloorDao;
import com.wms_backend.dao.InboundDao;
import com.wms_backend.dao.ShelfDao;
import com.wms_backend.dao.UserDao;
import com.wms_backend.entity.*;
import com.wms_backend.service.InboundService;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

@Service
public class InboundServiceImpl implements InboundService {

    @Autowired
    InboundDao inboundDao;

    @Autowired
    UserDao userDao;

    @Autowired
    FloorDao floorDao;

    @Autowired
    ShelfDao shelfDao;

    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;


    @Override
    public Result create(JSONObject param, String userId) {
        Inbound inbound = new Inbound();
        inbound.setCreateUser(userId);
        inbound.setName(param.getString("name"));
        inbound.setKind(param.getString("kind"));
        inbound.setUnit(param.getInteger("unit"));
        inbound.setInNumber(param.getInteger("number"));
        inbound.setOutNumber(0);
        inbound.setRemainNumber(param.getInteger("number"));
        inbound.setWarehouse(param.getString("warehouse"));
        inbound.setCreateTime(LocalDateTime.now().plusHours(8));
        inbound.setStatus(1);
        Integer companyId = userDao.findCompanyIdByUserId(userId).getCompanyId();
        inbound.setCompanyId(companyId);
        inboundDao.save(inbound);
        return Result.success();

    }


    @Override
    public Result check(JSONObject param, String userId) {
        Integer id = param.getInteger("id");

        Optional<Inbound> optionalInbound = inboundDao.findById(id);
        Integer inNumber = optionalInbound.get().getInNumber();
        Inbound inbound = optionalInbound.orElse(null);

        if (param.getInteger("pass") == 1) {
            if (inbound.getStatus() != 2) {
                List<Integer> list = floorDao.getSomeSpace(inNumber);
                if (list.size() < inNumber) {
                    return Result.error("仓库容量不足");
                }
                int index = 1;
                for (Integer i : list) {
                    int finalIndex = index;
                    //调用小车微服务
                    System.out.println("调用小车微服务");
                    JSONObject messageJsonObject = new JSONObject();
                    messageJsonObject.put("inboundId", inbound.getId());
                    messageJsonObject.put("order", finalIndex);
                    messageJsonObject.put("floorId", i);
                    String messageJsonString = messageJsonObject.toJSONString();
                    kafkaTemplate.send("vehicle", messageJsonString);
                    index++;
                }
                inbound.setStatus(2);

            }

        } else {
            inbound.setStatus(3);
        }
        inbound.setCheckReport(param.getString("checkReport"));
        inbound.setCheckTime(LocalDateTime.now().plusHours(8));
        inbound.setCheckUser(userId);
        inboundDao.save(inbound);
        return Result.success();
    }

    @Override
    public Result queryByCondition(JSONObject param, String userId) {
        User user = userDao.findCompanyIdByUserId(userId);
        Integer companyId = user.getCompanyId();
        //获取JSON中的参数
        String createUser = param.getString("createUser");
        String name = param.getString("name");
        String kind = param.getString("kind");
        Integer status = param.getInteger("status");
        Integer pageNum = param.getInteger("pageNum");
        Integer pageSize = param.getInteger("pageSize");
        //按条件查询
        Specification<Inbound> sc = new Specification<Inbound>() {
            @Override
            public Predicate toPredicate(Root<Inbound> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<>();
                if (createUser != null) {
                    list.add(cb.like(root.get("createUser"), "%" + createUser + "%"));
                }
                if (name != null) {
                    list.add(cb.like(root.get("name"), "%" + name + "%"));
                }
                if (kind != null) {
                    list.add(cb.like(root.get("kind"), "%" + kind + "%"));
                }
                if (status != null) {
                    list.add(cb.equal(root.get("status"), status));
                }
                list.add(cb.equal(root.get("companyId"), companyId));
                Predicate[] predicates = new Predicate[list.size()];
                list.toArray(predicates);
                return cb.and(predicates);
            }
        };
        if (pageSize == null || pageNum == null) {
            pageNum = 1;
            pageSize = 10;
        }
        Page<Inbound> result = inboundDao.findAll(sc, PageRequest.of(pageNum - 1, pageSize));
        return Result.success(result);
    }

    @Override
    public Result queryLocation(JSONObject param, String userId) {
        Integer inboundId = param.getInteger("inboundId");
        List<Floor> floorList = floorDao.findByInboundId(inboundId);
        List<LocationDetails> locationDetailsList = new ArrayList<>();
        for(Floor f : floorList){
            LocationDetails locationDetails = new LocationDetails();
            locationDetails.setFloorOrder(f.getFloorOrder());
            Optional<Shelf> shelfs = shelfDao.findById(f.getShelfId());
            Shelf shelf = shelfs.get();
            locationDetails.setShelfOrder(shelf.getShelfOrder());
            locationDetails.setRepositoryName(shelf.getRepositoryName());
            locationDetailsList.add(locationDetails);
        }
        return Result.success(locationDetailsList);
    }
}
